#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time
import serial
import os
from sqlobject.sqlbuilder import *

from podpurneFunkce import vytvorSoubor, vymazSoubor, vytvorRamDisk
from nacteniKonfigurace import cisloAutomatu, adresarDataTelemetrie, semaforNapeti230V_OK
from tabulky import SmsProOdeslani, UdalostiAutomatu

class DEX:
    def __init__(self, seriovyPort):                
        self.s= seriovyPort                        
    
    def nactiData(self, casoveRazitko = None, button = None):
        self.cisloButtonu = button
        if os.path.exists(semaforNapeti230V_OK): # nacitame jen kdyz je napeti OK
            try:
                if not casoveRazitko:
                    casoveRazitko = time.strftime('%Y.%m.%d_%H%M%S')
                self.casoveRazitko = casoveRazitko                
                self.masterHandshake()
                self.slaveHandshake()
                self.thirdHandshake()
                if self.nactenaData:
                    self.analzyujEvaData()
                    self.ulozEvaData()
                else:
                    vytvorSoubor("%sEVAdataSeNepodariloNacist_%s.dts" % (adresarDataTelemetrie, casoveRazitko))
            except Exception, e:
                print Exception
                print e
#TODO: zalogovani vyjimky (vyhucit to napriklad kdyz je vypnuty automat)

      
    def masterHandshake(self):
        self.switcher = 0
        dataString = "1234567890RR01L01" # VMC is slave /* COM_ID R REV_LEVEL */
        dataString = "\x10\x01" + dataString + "\x10\x03\xde\x4d" # data plus kontrolni soucet
        #'\x10' 16 DLE Data Link Escape
        #'\x01'  1 SOH Start Of Heading
        #'\x03'  3 ETX End of TeXt
        
        self.s.write('\x05') # '\x05' ENQ
#        print "zkousim prijimat"
        self.s.read(2) # automat by mel odpovedet \x10 \x30 (potvrzeni prijeti x05 ENQ)
        self.s.write(dataString)
        self.s.read(2) # automat by mel odpovedet \x10 \x31 (potvrzeni prijeti datastringu)        
        self.s.write('\x04') # EOT ='\x04' End of Transmission

    def slaveHandshake(self):
        self.s.read()#, "2. handshake, automat by se mel zeptat, co dal: ENQ x05"
        self.alternateAnswer()        
        while 1:            
            bajt = self.s.read()            
            if bajt in ("\x03", ""): # ETX = "\x03" End Of Text, nebo kdyz porucha a nenacteme data
                self.s.read(2) # dva bajty kontrlolni soucet                
                break
        self.alternateAnswer()
        self.s.read() # mel by odpovedet '\x04' EOT End Of Transmition
        

    def thirdHandshake(self):
        self.s.read() # ENQ '\x05' enquiry, automat se pta, co dal   
        self.alternateAnswer()
        self.nactenaData = ""        
        # zacneme ukladat nactena data
        while 1:
            bajt = self.s.read()            
            if bajt in ("\x10","\x04","" ): # DLE Data Line Escape, EOT End of Transmission, prazdny string = chyba nacitani dat
                if bajt in ("\x10", ):
                    # po DLE ma prijit STX, ETX nebo ETB     
                    bajt = self.s.read()
                    if bajt not in ("\x02", ): # STX Start of Text - trosku jednodussi vyhodnocovani pro Telit modul
                        # po ETX nebo ETB prichazi kontrolni soucet, ten take nezaznamenavame
                        self.s.read(2) # dva bajty kontrlolni soucet
                        self.alternateAnswer()
                elif bajt in ("\x04","" ): # EOT End of Transmission                     
                    break
            else:
                self.nactenaData = self.nactenaData + bajt
        print "tisknu nactena data"
        print self.nactenaData


    def alternateAnswer(self):        
        if self.switcher:            
            self.switcher = 0
            self.s.write("\x10\x31") # DLE + 30           
        else:            
            self.switcher = 1
            self.s.write("\x10\x30") # DLE + 31       
            
    def analzyujEvaData(self):
        radky = self.nactenaData.split("\n")
        for self.aktualniRadek in radky:
            if self.aktualniRadek.startswith("ID1*"):                
                self.zRadkuVytvorList()
                print self.listAktualniRadek
                # radek muze vypadat takto
                # ID1*FAS670     *  KRYSTAL   *0130*PA037**PA0037                
                (id, 
                self.machineSerNo,         # ID101   Machine Serial Number   FAS670 (FAS + max. 8 mist, cisla mozno v automatu FAS ze servisniho menu menit)
                self.machineModelNo,       # ID102   Machine Model Number    KRYSTAL
                self.machineBuildStandard, # ID103   Machine Build Standard  0130
                self.machineLocation,      # ID104   Machine Location        PA037 (alfanumeric, mozno v automatu FAS menit)
                self.customField,          # ID105   Custom Field            u automat FAS neni mozne nastavit (zustane nevyplneno)
                self.machineAssetNumber    # ID106   Machine Asset Number    PA0037 (alfanumeric, mozno menit)
                ) = self.listAktualniRadek
                self.machineSerNo = self.machineSerNo[3:] # v automatech FAS jsou na prvnich 3 mistech pismena, ta neukladame
                self.machineSerNo.zfill(8) # zleva doplnime nuly (vzdy ukladame 8 mist)
            elif self.aktualniRadek.startswith("MA5*ERROR"):
                # chyba v nactenych EVA datech z automatu FAS ma nasledujici format
                # MA5*ERROR*101006*1707*16*38
                print self.aktualniRadek
                self.zRadkuVytvorList()
                textChyby = "FAS KOD CHYBY: %s %s" % (self.listAktualniRadek[-2], self.listAktualniRadek[-1])                
                datum = time.strftime('%d.%m.%Y')
                # kdyz od pulnoci stejna chyba jeste nebyla zaznamenana do databaze
                # (stejnou chybu nepotrebujeme do databaze trvale ukladat a tak stale odesilat stejne SMS)
                if not len(list(SmsProOdeslani.select(AND(SmsProOdeslani.q.textZpravy==textChyby, 
                                                          SmsProOdeslani.q.tStamp > datum)))):
                    SmsProOdeslani(textZpravy = textChyby)
                    UdalostiAutomatu(popisUdalosti=textChyby, periferie = "ERROR")
    
    

    def zRadkuVytvorList(self):
        udaje = self.aktualniRadek
        udaje = udaje.split("*")        
        self.listAktualniRadek = ([x.strip() for x in udaje]) # osekame pripadne mezery
    
    def ulozEvaData(self):
        vytvorSoubor(cisloAutomatu, self.machineSerNo) # z nactenych EVA/DTS dat opakovane ukladame cislo automatu
        if self.cisloButtonu:
            predlohaNazvu = "%s_%s_%s_%s_%s_%s_%s.mny" # extenze souboru jako "money" 
            predlohaNazvu = "%s_%s" % (self.cisloButtonu, predlohaNazvu)
                                                       # (extenze odlisi nacteni dat vyvolane prilozenim iButtonu sacku na mince)
        else:
            predlohaNazvu = "%s_%s_%s_%s_%s_%s_%s.dts" # # extenze jako eva/DTS - 
        nazevSouboru = predlohaNazvu % (self.machineSerNo,         
                                        self.machineModelNo,       
                                        self.machineBuildStandard, 
                                        self.machineLocation,
                                        self.customField, 
                                        self.machineAssetNumber, 
                                        self.casoveRazitko, 
                                       )
        nazevSouboru = adresarDataTelemetrie + nazevSouboru
        print "nazev souboru:", nazevSouboru
        vytvorSoubor(nazevSouboru, self.nactenaData)

if __name__ == "__main__":    
    s = serial.Serial('/dev/ttyS1', 9600, 8, "N", stopbits=1, timeout=2, xonxoff=0)
    vytvorRamDisk()
    vytvorSoubor(semaforNapeti230V_OK)
    dex = DEX(seriovyPort = s)
    while 1:
        dex.nactiData()
        time.sleep(60*2) # dve minuty
